<!doctype html>



  


<html class="theme-next pisces use-motion">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  
  
  <link href="/vendors/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/vendors/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.0.1" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="王雨峰, 博客" />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.0.1" />






<meta name="description" content="其实也不是笔记，我上课从来不记笔记，呃，懒。
结合参考资料，写一写我对这几天学习内容的想法。大家可选择性阅读。
有些东西是上课没说到的。
##010101
先从二进制说起。
####为什么计算机需要用二进制存储数据？
二进制中只有「0」和「1」。
计算机是通电的，那么在电的世界中，

没通电的的就是「0」，通电的就是「1」。
为什么是二进制呢？因为这种「无」和「有」的二元对立关系，是非常好实现的。">
<meta property="og:type" content="article">
<meta property="og:title" content="数制，原反补码，浮点数学习笔记">
<meta property="og:url" content="http://wangyufeng.org/2015/09/10/原、反、补码学习笔记/index.html">
<meta property="og:site_name" content="王雨峰的博客">
<meta property="og:description" content="其实也不是笔记，我上课从来不记笔记，呃，懒。
结合参考资料，写一写我对这几天学习内容的想法。大家可选择性阅读。
有些东西是上课没说到的。
##010101
先从二进制说起。
####为什么计算机需要用二进制存储数据？
二进制中只有「0」和「1」。
计算机是通电的，那么在电的世界中，

没通电的的就是「0」，通电的就是「1」。
为什么是二进制呢？因为这种「无」和「有」的二元对立关系，是非常好实现的。">
<meta property="og:image" content="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/72692184.jpg">
<meta property="og:image" content="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/88810670.jpg">
<meta property="og:image" content="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/92889196.jpg">
<meta property="og:image" content="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/27697363.jpg">
<meta property="og:updated_time" content="2015-09-10T13:56:10.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="数制，原反补码，浮点数学习笔记">
<meta name="twitter:description" content="其实也不是笔记，我上课从来不记笔记，呃，懒。
结合参考资料，写一写我对这几天学习内容的想法。大家可选择性阅读。
有些东西是上课没说到的。
##010101
先从二进制说起。
####为什么计算机需要用二进制存储数据？
二进制中只有「0」和「1」。
计算机是通电的，那么在电的世界中，

没通电的的就是「0」，通电的就是「1」。
为什么是二进制呢？因为这种「无」和「有」的二元对立关系，是非常好实现的。">
<meta name="twitter:image" content="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/72692184.jpg">



<script type="text/javascript" id="hexo.configuration">
  var NexT = window.NexT || {};
  var CONFIG = {
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: 0,
      author: '博主'
    }
  };
</script>




  <link rel="canonical" href="http://wangyufeng.org/2015/09/10/原、反、补码学习笔记/"/>

  <title> 数制，原反补码，浮点数学习笔记 | 王雨峰的博客 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  










  
  
    
  

  <div class="container one-collumn sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">王雨峰的博客</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">随便写点东西，为互联网贡献一些比特~</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>

 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  
  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                数制，原反补码，浮点数学习笔记
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            <span class="post-meta-item-icon">
              <i class="fa fa-calendar-o"></i>
            </span>
            <span class="post-meta-item-text">发表于</span>
            <time itemprop="dateCreated" datetime="2015-09-10T14:30:58+08:00" content="2015-09-10">
              2015-09-10
            </time>
          </span>

          

          
            
          

          

          
          

          
        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>其实也不是笔记，我上课从来不记笔记，呃，懒。</p>
<p>结合参考资料，写一写我对这几天学习内容的想法。大家可选择性阅读。</p>
<p>有些东西是上课没说到的。</p>
<p>##010101</p>
<p>先从二进制说起。</p>
<p>####为什么计算机需要用二进制存储数据？</p>
<p>二进制中只有「0」和「1」。</p>
<p>计算机是通电的，那么在电的世界中，</p>
<p><img src="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/72692184.jpg" alt=""></p>
<p>没通电的的就是「0」，通电的就是「1」。</p>
<p>为什么是二进制呢？因为这种「无」和「有」的二元对立关系，是非常好实现的。试想，如果要造一个「十进制计算机」，那就要创造出一种能够表达10种状态的东西，还得能够对这10种状态进行准确的观察、计算，难度很大。「电」的特性正好满足二进制的需求。「高电平」就是1，「低电平」就是0。</p>
<p>你可能会问了，那电压有大有小的，为啥就只有0和1，不会出个0.5呢？</p>
<p>如果是计科的同学，咱们这学期在同时学的两门课「数电」（数字逻辑）和「模电」（电路设计），就和这相关。数电是抽象，把电路抽象成0和1，关注其中的逻辑部分，性质是离散的。而模电就是研究具体的电路，和实际世界关系紧密，性质是连续的。</p>
<p>如果说这是数字电路的话：</p>
<p><img src="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/88810670.jpg" alt=""></p>
<p>那这就是模拟电路：</p>
<p><img src="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/92889196.jpg" alt=""></p>
<p>##进制</p>
<p>一张很有意思的漫画：</p>
<p><img src="http://7xku3h.com1.z0.glb.clouddn.com/15-9-10/27697363.jpg" alt=""></p>
<p>收藏多年。很有意思。</p>
<p>人类之所以用十进制，很可能跟人类长了10跟手指头有关系。在计算机中，2进制-8进制-16进制的互换是很方便的。可以想象，如果人类进化出8根手指头，学习计算机的难度大概会大大降低。或者说，人类长了<code>2^n,n∈k</code>跟手指头。哈。</p>
<p>##为什么课本上的原码、反码和补码都是8位？<br>在计算机中，一位0或者1叫做一个<code>比特</code>，8个比特可组成一个<code>字节</code>。所以8位是很常用的。在C语言中，int型占用4个字节，也就是32位。double型占用8个字节，即64位。</p>
<p>书上都写成八位，大概是为了方便吧，毕竟8位的用途很广，最早的CPU也是8位的。课本上没说理由。</p>
<p>另外，不论是原、反、补码，最高位（最左边那位）都是符号位，1是负数，0是正数。也就是说具体的数值的部分，只能靠7位比特来实现。</p>
<p>##原、反、补码<br>大家在刚学C语言的时候，大概都会遇到一个现象，就是<code>溢出</code></p>
<p>比如我有<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">int n = 2147483647;</div></pre></td></tr></table></figure></p>
<p>这是int型能表达的最大值，这时我<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">n++; printf(n);</div></pre></td></tr></table></figure></p>
<p>这时候n显示的值是<code>-2147483648</code></p>
<p><strong>从最大值变成了最小值！</strong>发生了什么呢，从课堂上的内容就很好理解，因为<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">01111111111111111111111111111111 + 1 =</div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">10000000000000000000000000000000</div></pre></td></tr></table></figure>
<p>最前面的1意味着这是一个负数。</p>
<p><em>到现在我也没太想清楚，一个范围内最小的这个数，补码是怎样被处理的。求指点。</em></p>
<hr>
<p>这里假定大家对原码、反码和补码的特征已经掌握了，那咱们来分别分析一下。</p>
<p>###原码</p>
<p>原码的最高位是符号位。其他位数表示数值。</p>
<p>在课上，咱们了解到原码有个缺点是<code>同时有+0和-0</code>，其实这还不是什么严重的问题。毕竟<code>-0</code>在计算机中是有用的，后面说到。</p>
<p>“绝对值相等的正数和负数”相加应该是<code>0</code>，但是在原码中<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">1+(-1) 即 0001 + 1001 = 1010</div></pre></td></tr></table></figure></p>
<p><code>1010</code>在原码中明显是<code>-2</code>. 正1和负1相加，得负2.</p>
<blockquote>
<p>坑爹啊，原码根本没法用。</p>
</blockquote>
<p>###反码</p>
<p>为了保证正负数相加得0，便采用了反码。</p>
<p>比如在四位的反码中<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">7 + 1 即 0111 + 0001 = 1000</div></pre></td></tr></table></figure></p>
<p>即<code>7 + 1 = -7</code></p>
<p>此时反码就已经有了”<em>表示范围内的最大的数+1，等于表示范围内的最小的数</em>“这一特征。(即溢出)</p>
<p>反码巧妙地解决了原码正负数相加不得零的问题。但是还有个遗留问题，就是<strong>仍然有正负两个0</strong>。</p>
<p>其实负0在某些情况下是有用的，在<code>Javascript</code>语言中就有负0.有时候，当一个负数特别特别接近零，以至于精度都不足以将它显示出来时，就表示为-0.以便和真正的0区分开来。</p>
<p>###补码<br>补码就是为了解决正负两个0的问题。</p>
<p>通俗来讲，补码就是在反码的基础上，把所有负数的表示范围减小了一格。例如原来能表示<code>-7 ~ -0</code>，现在就能表示<code>-8 ~ -1</code>，-0自然就没有了。</p>
<p>补码在”绝对值相等的正负数相加”这件事儿上，一定会产生一个<code>进位</code>，把<code>进位</code>舍弃后，结果即为0.</p>
<p>现在正1加负1就得0了，正确。</p>
<p>###溢出<br>溢出的本质现在就明白了。正是因为数字在计算机中全部以补码表示，而补码的特点就是会溢出。</p>
<p>其实别的语言还好，但C语言的设计思路就是「充分信任程序员」，所以C语言假定你很清楚「int型的最大值是2147483647」。呵呵。</p>
<p>##再论补码</p>
<p>理论上，补码的学名是<code>2的补码</code>或<code>2的补数</code>，即「Two’s Complement」.</p>
<p>重温一下，补码的转换方式是</p>
<ol>
<li>各位取反</li>
<li>加1</li>
</ol>
<p>其实对于计算机来说，采用什么码都可以，比如咱们今天上课讲到「BCD码」，BCD码中竟然就有「8421码」、「2421码」、「余3码」等等等等种类。只要能在数字和编码之间，形成一一对应的关系即可。但不同种类的编码自然有不同的特点。为什么补码用来表示计算机中的一切数字呢？</p>
<p>根据查到的资料来看，补码的优点之一是：<strong>如果使用补码，那么所有的加法都可以用一种电路完成。</strong></p>
<p>老师在课上提到，在计算机中，减法会被归约为加法。比如</p>
<p>$$<br>5 - 3 → 5 + (-3)<br>$$</p>
<p>而原码就没法做这种规约，如果使用原码的话，加法是一套电路（加法器），还需要专门实现一套「减法器」。</p>
<p>##定点数和浮点数<br>似乎课上对于这两样东西只是一带而过，这里简单提一提。</p>
<p>定点数：小数点是固定的(即位置是默认的)。比如说银行存款的系统，就适合用定点数来表示，因为存款的话，需要在计算机中储存的数字，都是只有小数点后两位（100,000.00￥）。定点数中，小数点的位置是由硬件/软件固定好的。</p>
<p>浮点数：就是咱们在计算机中常用的用来储存小数的方法。float和double都算是浮点数。</p>
<p>咱们学过科学计数法。浮点数的实现依托于科学计数法。咱们来分析一下<code>double型</code>。</p>
<p>double的学名是<code>双精度浮点数</code>。前面提到，double型占用8个字节，即64位。那这64位都是干啥的呢？</p>
<p>位数的分配如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">s = 1 位符号位 | e = 11 位指数位 | f = 52位有效数字</div></pre></td></tr></table></figure>
<p>它形如<br>$$<br>(-1)^s*1.f*2^{e-1023}<br>$$</p>
<p>为什么最左边是-1的s次方呢？因为<code>s=0</code>的话，该数就是正数，如果s = 1的话，改数就是负数。<strong>这就是「最高位符号位」的实现原理</strong>。巧妙吧。</p>
<p>那个1023是偏移量，跟无符号数转为有符号数有关(即把一半的表示范围分给负数部分)。</p>
<p>细节就略过了，反正我也不懂。符号位即是管正负的。指数为决定了小数点的位置，所以叫<strong>浮点数</strong>。就好比是科学计数法中，e后边的数字。表示这个纯小数乘10的多少次方。每乘一个10，小数点向左浮动一位。反之亦然。</p>
<p>大家知道，电脑中有两个重要的部件，分别是「CPU」和「GPU」。GPU也即显卡的核心芯片。那为什么GPU用来运算图形就特别快，而CPU就无法胜任呢？因为<strong>GPU是专门用来计算浮点数的</strong>。而计算机要想显示出图形来，就需要运算大量的浮点数。为啥GPU算浮点数就快呢？大概跟硬件层面上的设计和指令集有关系吧，毕竟术业有专攻。</p>
<p>现在挖比特币，超级计算机阵列等等，都大量使用GPU，因为这些任务都对浮点数的运算有高要求。</p>
<p>##拓展阅读：</p>
<p>说一下浮点数的形式中的<code>f</code>和<code>e</code>。</p>
<p>在<code>Javascript</code>这门语言中，根本就没有整数，一切数字都是用浮点数表示的。在Javascript中，除了普通的数字，还有NaN，+Infinity，-Infinity。</p>
<p>参考上方的「double型浮点数的形式」，在Javascript中有如下处理：</p>
<ul>
<li>当 e = 0 且 f = 0 时，该数为0；</li>
<li>当 e = 255 且 f = 0 时，该数为±Infinity(正负无穷)，具体的正负值由s决定。</li>
<li>当 e = 255 且 f ≠ 0 时，该数位NaN(Not a Number)。即「不是一个数」。比如除数为0时，结果就是NaN。</li>
</ul>
<p>计算机的电路很原始的，大概只能算算加法，做做位运算。什么乘啊除啊都没法直接做，更遑论那些函数啥的了。但计算机毕竟是离散的，而且也是不嫌烦的。比如说要计算正弦函数，对<code>Sin(x)</code>进行泰勒展开，有<br>$$<br>sin(x)=x-x^3/3!+x^5/5!-x^7/7!+……<br>$$<br>大约只需要展开六七项，精度就可以满足double类型的精度了。</p>
<p>别问我泰勒展开是啥，我不会（泪目）。大一的同学们，且听我一言：</p>
<p><strong>请一定要好好学高等数学。和一切数学。</strong></p>
<hr>
<blockquote>
<p>参考资料</p>
<p>〔1〕赵岩 . C语言点滴 . 人民邮电出版社, P58</p>
<p>〔2〕Charles Petzold . CODE . 电子工业出版社, P365</p>
<p>〔3〕贾熹滨等 . 数字逻辑基础与Verilog硬件描述语言 . 清华大学出版社, P9</p>
</blockquote>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>

    <footer class="post-footer">
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2015/09/09/programming-guide-for-freshman-3/" rel="next" title="计算机专业新生指南(之三)">
                <i class="fa fa-chevron-left"></i> 计算机专业新生指南(之三)
              </a>
            
          </div>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2015/09/15/Mountain/" rel="prev" title="Mountain">
                Mountain <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel ">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/avatar.gif"
               alt="Alan" />
          <p class="site-author-name" itemprop="name">Alan</p>
          <p class="site-description motion-element" itemprop="description">Alan Wang's personal blog.</p>
        </div>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">57</span>
              <span class="site-state-item-name">日志</span>
            </a>
          </div>

          
            <div class="site-state-item site-state-categories">
              
                <span class="site-state-item-count">9</span>
                <span class="site-state-item-name">分类</span>
              
            </div>
          

          
            <div class="site-state-item site-state-tags">
              
                <span class="site-state-item-count">4</span>
                <span class="site-state-item-name">标签</span>
              
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
        </div>

        
        

        
        

      </section>

      
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">
            
              
            
            
              <p class="post-toc-empty">此文章未包含目录</p>
            
          </div>
        </section>
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2016</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Alan</span>
</div>

<div class="powered-by">
  Powered by <a class="theme-link" href="https://hexo.io">Hexo</a> 
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>

        

        
      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  



  
  <script type="text/javascript" src="/vendors/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/vendors/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/vendors/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/vendors/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/vendors/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/vendors/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.0.1"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.0.1"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.0.1"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.0.1"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.0.1"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.0.1"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.0.1"></script>



  



  




  
  

  

  

  

</body>
</html>
